#pragma once
#include <type_traits>
#include <utility>		// for std::move

namespace gl
{
	namespace utils
	{
		template <class T>
		struct ease_out
		{
			using value_type = std::decay_t<T>;

			ease_out() = default;
			ease_out(value_type target) : value{std::move(target)}, target_{value} {}
			ease_out(value_type target, value_type x) : value{std::move(x)}, target_{std::move(target)} {}

			auto& get() { return value; }
			auto& get() const { return value; }
			auto& target() { return target_; }
			auto& target() const { return target_; }
			void set(value_type x) { target_ = std::move(x); }
			void update(float speed=0.2) { value = (1-speed)*value + speed*target_; }

			void operator () () { update(); }
			operator auto& () { return get(); }
			operator auto& () const { return get(); }
			auto& operator = (value_type x) { set(std::move(x)); return *this; }
			auto& operator += (value_type const&x) { target_ += x; return *this; }
			auto& operator -= (value_type const&x) { target_ -= x; return *this; }
			void flip() { target_ = !target_; }

		private:
			value_type value;
			value_type target_;
		};
	}

	using utils::ease_out;
}

